package me.yxy.mobanddd.components.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * 对Controller的Respnose进行适当的格式化，特别是
 */
@Component
@Aspect
@SuppressWarnings("unused")
public class ResponseFormatAspect extends BaseAspect{

    private static final Logger ASPECT_LOG = LoggerFactory.getLogger(ResponseFormatAspect.class);

//    @Around("within(@org.springframework.web.bind.annotation.RestController *)")
    public Object formatAround(ProceedingJoinPoint pjp) throws Throwable {

        ClassEntry classEntry = getCurrentClassInfo(pjp);
        if(classEntry==null){
            return pjp.proceed();
        }


        //TODO 这里还可以加一个方法，可以通过某些注解禁用掉这里的逻辑，以提高性能，或者，在一个View上，指定（处理/不处理）

        Object response = pjp.proceed();

        //报表查询基本都是Page
        if(response instanceof Page){
            formatWithinPage((Page)response);
        }

        //一般列表查询，将会是List居多
        else if(response instanceof Collection){
            Iterator tor = ((Iterable)response).iterator();
            while(tor.hasNext()){
                formatObject(tor.next());
            }
        }

        //其他单值查询
        else{
            formatObject(response);
        }

        return response;
    }

    private void formatWithinPage(Page response) {
        List content = response.getContent();
        if(ObjectUtils.isEmpty(content)){
            return;
        }

        for (Object item : content) {
            formatObject(item);
        }
    }

    //TODO 暂时还不支持迭代处理
    private void formatObject(Object response) {

        //检查每个属性，如果其中有Date类型，那么找对应的Str结尾的属性，并格式化处理
        Field[] fields = response.getClass().getDeclaredFields();
        if(ObjectUtils.isEmpty(fields)){
            return;
        }

        for (Field field : fields) {
            if(field.getType().equals(Date.class)){
                formatDate(response,field);
            }
        }

    }

    private void formatDate(Object response, Field field) {
        try {
            Field stringField = response.getClass().getDeclaredField(field.getName()+"Str");

            field.setAccessible(true);
            Date originalDate = ((Date)field.get(response));

            //TODO 应该还能找到性能更好的组件
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//TODO can be configurable
            stringField.setAccessible(true);
            stringField.set(response,simpleDateFormat.format(originalDate));

        } catch (NoSuchFieldException | IllegalAccessException e) {
        }
    }

}
